home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / ppm / ppmtotga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-06  |  11.6 KB  |  453 lines

  1. /* ppmtotga.c - read a portable pixmap and produce a TrueVision Targa file
  2. **
  3. ** Copyright (C) 1989, 1991 by Mark Shand and Jef Poskanzer
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "ppm.h"
  14. #include "ppmcmap.h"
  15. #include "tga.h"
  16.  
  17. /* Max number of colors allowed for colormapped output. */
  18. #define MAXCOLORS 256
  19.  
  20. /* Forward routines. */
  21. static void writetga ARGS(( struct ImageHeader* tgaP, char* id ));
  22. static void put_map_entry ARGS(( pixel* valueP, int size, pixval maxval ));
  23. static void compute_runlengths ARGS(( int cols, pixel* pixelrow, int* runlength ));
  24. static void put_pixel ARGS(( pixel* pP, int imgtype, pixval maxval, colorhash_table cht ));
  25. static void put_mono ARGS(( pixel* pP, pixval maxval ));
  26. static void put_map ARGS(( pixel* pP, colorhash_table cht ));
  27. static void put_rgb ARGS(( pixel* pP, pixval maxval ));
  28.  
  29. /* Routines. */
  30.  
  31. void
  32. main( argc, argv )
  33.     int argc;
  34.     char* argv[];
  35.     {
  36.     FILE* ifp;
  37.     pixel** pixels;
  38.     register pixel* pP;
  39.     pixel p;
  40.     int argn, rle_flag, rows, cols, ncolors, row, col, i, format, realrow;
  41.     pixval maxval;
  42.     colorhist_vector chv;
  43.     colorhash_table cht;
  44.     char out_name[100];
  45.     char* cp;
  46.     int* runlength;
  47.     char* usage = "[-name <tganame>] [-mono|-cmap|-rgb] [-norle] [ppmfile]";
  48.     struct ImageHeader tgaHeader;
  49.  
  50.     ppm_init( &argc, argv );
  51.     out_name[0] = '\0';
  52.  
  53.     /* Check for command line options. */
  54.     argn = 1;
  55.     tgaHeader.ImgType = TGA_Null;
  56.     rle_flag = 1;
  57.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  58.         {
  59.         if ( pm_keymatch( argv[argn], "-name", 2 ) )
  60.             {
  61.             ++argn;
  62.             if ( argn == argc )
  63.             pm_usage( usage );
  64.             (void) strcpy( out_name, argv[argn] );
  65.             }
  66.         else if ( pm_keymatch( argv[argn], "-cmap", 2 ) )
  67.             tgaHeader.ImgType = TGA_Map;
  68.         else if ( pm_keymatch( argv[argn], "-mono", 2 ) )
  69.             tgaHeader.ImgType = TGA_Mono;
  70.         else if ( pm_keymatch( argv[argn], "-rgb", 2 ) )
  71.             tgaHeader.ImgType = TGA_RGB;
  72.         else if ( pm_keymatch( argv[argn], "-norle", 2 ) )
  73.             rle_flag = 0;
  74.         else
  75.             pm_usage( usage );
  76.         ++argn;
  77.         }
  78.  
  79.     if ( argn != argc )
  80.         {
  81.         /* Open the input file. */
  82.         ifp = pm_openr( argv[argn] );
  83.  
  84.         /* If output filename not specified, use input filename as default. */
  85.         if ( out_name[0] == '\0' )
  86.             {
  87.             (void) strcpy( out_name, argv[argn] );
  88.             cp = index( out_name, '.' );
  89.             if ( cp != 0 )
  90.             *cp = '\0';    /* remove extension */
  91.             if ( strcmp( out_name, "-" ) == 0 )
  92.             (void) strcpy( out_name, "noname" );
  93.             }
  94.  
  95.         ++argn;
  96.         }
  97.     else
  98.         {
  99.         /* No input file specified. */
  100.         ifp = stdin;
  101.         if ( out_name[0] == '\0' )
  102.             (void) strcpy( out_name, "noname" );
  103.         }
  104.  
  105.     if ( argn != argc )
  106.         pm_usage( usage );
  107.  
  108.     /* Read in the ppm file. */
  109.     ppm_readppminit( ifp, &cols, &rows, &maxval, &format);
  110.     pixels = ppm_allocarray( cols, rows );
  111.     for ( row = 0; row < rows; ++row )
  112.     ppm_readppmrow( ifp, pixels[row], cols, maxval, format );
  113.     pm_close( ifp );
  114.  
  115.     /* Figure out the colormap. */
  116.     switch ( PPM_FORMAT_TYPE( format ) )
  117.     {
  118.         case PPM_TYPE:
  119.     if ( tgaHeader.ImgType == TGA_Mono )
  120.         pm_error( "input is not a graymap, filter through ppmtopgm first" );
  121.     if ( tgaHeader.ImgType == TGA_Null || tgaHeader.ImgType == TGA_Map )
  122.         {
  123.         pm_message( "computing colormap..." );
  124.         chv = ppm_computecolorhist(
  125.         pixels, cols, rows, MAXCOLORS, &ncolors );
  126.         if ( chv == (colorhist_vector) 0 )
  127.         {
  128.         if ( tgaHeader.ImgType == TGA_Map )
  129.             pm_error(
  130.             "too many colors - try doing a 'ppmquant %d'",
  131.             MAXCOLORS );
  132.         else
  133.             tgaHeader.ImgType = TGA_RGB;
  134.         }
  135.         else
  136.         {
  137.         pm_message( "%d colors found", ncolors );
  138.         if ( tgaHeader.ImgType == TGA_Null )
  139.             tgaHeader.ImgType = TGA_Map;
  140.         }
  141.         }
  142.     break;
  143.  
  144.         case PGM_TYPE:
  145.         case PBM_TYPE:
  146.     if ( tgaHeader.ImgType == TGA_Null )
  147.         tgaHeader.ImgType = TGA_Mono;
  148.     else if ( tgaHeader.ImgType == TGA_Map )
  149.         {
  150.         pm_message( "computing colormap..." );
  151.         chv = ppm_computecolorhist(
  152.         pixels, cols, rows, MAXCOLORS, &ncolors );
  153.         if ( chv == (colorhist_vector) 0 )
  154.         pm_error( "can't happen" );
  155.         pm_message( "%d colors found", ncolors );
  156.         }
  157.     break;
  158.  
  159.         default:
  160.     pm_error( "can't happen" );
  161.     }
  162.  
  163.     if ( rle_flag )
  164.     {
  165.     switch ( tgaHeader.ImgType )
  166.         {
  167.         case TGA_Mono:
  168.         tgaHeader.ImgType = TGA_RLEMono;
  169.         break;
  170.         case TGA_Map:
  171.         tgaHeader.ImgType = TGA_RLEMap;
  172.         break;
  173.         case TGA_RGB:
  174.         tgaHeader.ImgType = TGA_RLERGB;
  175.         break;
  176.         default:
  177.         pm_error( "can't happen" );
  178.         }
  179.     runlength = (int*) pm_allocrow( cols, sizeof(int) );
  180.     }
  181.     
  182.     tgaHeader.IDLength = 0;
  183.     tgaHeader.Index_lo = 0;
  184.     tgaHeader.Index_hi = 0;
  185.     if ( tgaHeader.ImgType == TGA_Map || tgaHeader.ImgType == TGA_RLEMap )
  186.     {
  187.         /* Make a hash table for fast color lookup. */
  188.         cht = ppm_colorhisttocolorhash( chv, ncolors );
  189.  
  190.         tgaHeader.CoMapType = 1;
  191.         tgaHeader.Length_lo = ncolors % 256;
  192.         tgaHeader.Length_hi = ncolors / 256;
  193.         tgaHeader.CoSize = 24;
  194.     }
  195.     else
  196.     {
  197.         tgaHeader.CoMapType = 0;
  198.         tgaHeader.Length_lo = 0;
  199.         tgaHeader.Length_hi = 0;
  200.         tgaHeader.CoSize = 0;
  201.     }
  202.     if ( tgaHeader.ImgType == TGA_RGB || tgaHeader.ImgType == TGA_RLERGB )
  203.     tgaHeader.PixelSize = 24;
  204.     else
  205.     tgaHeader.PixelSize = 8;
  206.     tgaHeader.X_org_lo = tgaHeader.X_org_hi = 0;
  207.     tgaHeader.Y_org_lo = tgaHeader.Y_org_hi = 0;
  208.     tgaHeader.Width_lo = cols % 256;
  209.     tgaHeader.Width_hi = cols / 256;
  210.     tgaHeader.Height_lo = rows % 256;
  211.     tgaHeader.Height_hi = rows / 256;
  212.     tgaHeader.AttBits = 0;
  213.     tgaHeader.Rsrvd = 0;
  214.     tgaHeader.IntrLve = 0;
  215.     tgaHeader.OrgBit = 0;
  216.  
  217.     /* Write out the Targa header. */
  218.     writetga( &tgaHeader, (char*) 0 );
  219.  
  220.     if ( tgaHeader.ImgType == TGA_Map || tgaHeader.ImgType == TGA_RLEMap )
  221.     {
  222.         /* Write out the Targa colormap. */
  223.         for ( i = 0; i < ncolors; ++i )
  224.             put_map_entry( &chv[i].color, tgaHeader.CoSize, maxval );
  225.     }
  226.  
  227.     /* Write out the pixels */
  228.     for ( row = 0; row < rows; ++row )
  229.     {
  230.     realrow = row;
  231.     if ( tgaHeader.OrgBit == 0 )
  232.         realrow = rows - realrow - 1;
  233.     if ( rle_flag )
  234.         {
  235.         compute_runlengths( cols, pixels[realrow], runlength );
  236.         for ( col = 0; col < cols; )
  237.         {
  238.         if ( runlength[col] > 0 )
  239.             {
  240.             putchar( 0x80 + runlength[col] - 1 );
  241.             put_pixel(
  242.             &(pixels[realrow][col]),
  243.             tgaHeader.ImgType, maxval, cht );
  244.             col += runlength[col];
  245.             }
  246.         else if ( runlength[col] < 0 )
  247.             {
  248.             putchar( -runlength[col] - 1 );
  249.             for ( i = 0; i < -runlength[col]; ++i )
  250.             put_pixel(
  251.                 &(pixels[realrow][col + i]),
  252.                 tgaHeader.ImgType, maxval, cht );
  253.             col += -runlength[col];
  254.             }
  255.         else
  256.             pm_error( "can't happen" );
  257.         }
  258.         }
  259.     else
  260.         {
  261.         for ( col = 0, pP = pixels[realrow]; col < cols; ++col, ++pP )
  262.         put_pixel( pP, tgaHeader.ImgType, maxval, cht );
  263.         }
  264.     }
  265.  
  266.     pm_close (stdout);
  267.     exit( 0 );
  268.     }
  269.  
  270. static void
  271. writetga( tgaP, id )
  272.     struct ImageHeader* tgaP;
  273.     char* id;
  274.     {
  275.     unsigned char flags;
  276.  
  277.     putchar( tgaP->IDLength );
  278.     putchar( tgaP->CoMapType );
  279.     putchar( tgaP->ImgType );
  280.     putchar( tgaP->Index_lo );
  281.     putchar( tgaP->Index_hi );
  282.     putchar( tgaP->Length_lo );
  283.     putchar( tgaP->Length_hi );
  284.     putchar( tgaP->CoSize );
  285.     putchar( tgaP->X_org_lo );
  286.     putchar( tgaP->X_org_hi );
  287.     putchar( tgaP->Y_org_lo );
  288.     putchar( tgaP->Y_org_hi );
  289.     putchar( tgaP->Width_lo );
  290.     putchar( tgaP->Width_hi );
  291.     putchar( tgaP->Height_lo );
  292.     putchar( tgaP->Height_hi );
  293.     putchar( tgaP->PixelSize );
  294.     flags = ( tgaP->AttBits & 0xf ) | ( ( tgaP->Rsrvd & 0x1 ) << 4 ) |
  295.         ( ( tgaP->OrgBit & 0x1 ) << 5 ) | ( ( tgaP->OrgBit & 0x3 ) << 6 );
  296.     putchar( flags );
  297.     if ( tgaP->IDLength )
  298.         fwrite( id, 1, (int) tgaP->IDLength, stdout );
  299.     }
  300.     
  301. #if __STDC__
  302. static void
  303. put_map_entry( pixel* valueP, int size, pixval maxval )
  304. #else /*__STDC__*/
  305. static void
  306. put_map_entry( valueP, size, maxval )
  307.     pixel* valueP;
  308.     int size;
  309.     pixval maxval;
  310. #endif /*__STDC__*/
  311.     {
  312.     int j;
  313.     pixel p;
  314.     
  315.     switch ( size )
  316.     {
  317.     case 8:                /* Grey scale. */
  318.     put_mono( valueP, maxval );
  319.     break;
  320.  
  321.     case 16:            /* 5 bits each of red green and blue. */
  322.     case 15:            /* Watch for byte order. */
  323.     PPM_DEPTH( p, *valueP, maxval, 31 );
  324.     j = (int) PPM_GETB( p ) | ( (int) PPM_GETG( p ) << 5 ) |
  325.         ( (int) PPM_GETR( p ) << 10 );
  326.     putchar( j % 256 );
  327.     putchar( j / 256 );
  328.     break;
  329.  
  330.     case 32:
  331.     case 24:            /* 8 bits each of blue green and red. */
  332.     put_rgb( valueP, maxval );
  333.     break;
  334.  
  335.     default:
  336.     pm_error( "unknown colormap pixel size (#2) - %d", size );
  337.     }
  338.     }
  339.  
  340. static void
  341. compute_runlengths( cols, pixelrow, runlength )
  342.     int cols;
  343.     pixel* pixelrow;
  344.     int* runlength;
  345.     {
  346.     int col, start;
  347.  
  348.     /* Initialize all run lengths to 0.  (This is just an error check.) */
  349.     for ( col = 0; col < cols; ++col )
  350.     runlength[col] = 0;
  351.     
  352.     /* Find runs of identical pixels. */
  353.     for ( col = 0; col < cols; )
  354.     {
  355.     start = col;
  356.     do {
  357.         ++col;
  358.         }
  359.     while ( col < cols &&
  360.         col - start < 128 &&
  361.         PPM_EQUAL( pixelrow[col], pixelrow[start] ) );
  362.     runlength[start] = col - start;
  363.     }
  364.     
  365.     /* Now look for runs of length-1 runs, and turn them into negative runs. */
  366.     for ( col = 0; col < cols; )
  367.     {
  368.     if ( runlength[col] == 1 )
  369.         {
  370.         start = col;
  371.         while ( col < cols &&
  372.             col - start < 128 &&
  373.             runlength[col] == 1 )
  374.         {
  375.         runlength[col] = 0;
  376.         ++col;
  377.         }
  378.         runlength[start] = - ( col - start );
  379.         }
  380.     else
  381.         col += runlength[col];
  382.     }
  383.     }
  384.  
  385. #if __STDC__
  386. static void
  387. put_pixel( pixel* pP, int imgtype, pixval maxval, colorhash_table cht )
  388. #else /*__STDC__*/
  389. static void
  390. put_pixel( pP, imgtype, maxval, cht )
  391.     pixel* pP;
  392.     int imgtype;
  393.     pixval maxval;
  394.     colorhash_table cht;
  395. #endif /*__STDC__*/
  396.     {
  397.     switch ( imgtype )
  398.     {
  399.     case TGA_Mono:
  400.     case TGA_RLEMono:
  401.     put_mono( pP, maxval );
  402.     break;
  403.     case TGA_Map:
  404.     case TGA_RLEMap:
  405.     put_map( pP, cht );
  406.     break;
  407.     case TGA_RGB:
  408.     case TGA_RLERGB:
  409.     put_rgb( pP, maxval );
  410.     break;
  411.     default:
  412.     pm_error( "can't happen" );
  413.     }
  414.     }
  415.  
  416. #if __STDC__
  417. static void
  418. put_mono( pixel* pP, pixval maxval )
  419. #else /*__STDC__*/
  420. static void
  421. put_mono( pP, maxval )
  422.     pixel* pP;
  423.     pixval maxval;
  424. #endif /*__STDC__*/
  425.     {
  426.     PPM_DEPTH( *pP, *pP, maxval, (pixval) 255 );
  427.     putchar( PPM_GETR( *pP ) );
  428.     }
  429.  
  430. static void
  431. put_map( pP, cht )
  432.     pixel* pP;
  433.     colorhash_table cht;
  434.     {
  435.     putchar( ppm_lookupcolor( cht, pP ) );
  436.     }
  437.  
  438. #if __STDC__
  439. static void
  440. put_rgb( pixel* pP, pixval maxval )
  441. #else /*__STDC__*/
  442. static void
  443. put_rgb( pP, maxval )
  444.     pixel* pP;
  445.     pixval maxval;
  446. #endif /*__STDC__*/
  447.     {
  448.     PPM_DEPTH( *pP, *pP, maxval, (pixval) 255 );
  449.     putchar( PPM_GETB( *pP ) );
  450.     putchar( PPM_GETG( *pP ) );
  451.     putchar( PPM_GETR( *pP ) );
  452.     }
  453.